package im.composer.generators;

import jass.engine.BufferNotAvailableException;
import jass.engine.SinkIsFullException;

import java.util.Vector;

import org.jaudiolibs.audioservers.AudioConfiguration;
import org.tritonus.share.sampled.FloatSampleBuffer;

import im.composer.audio.engine.InOut;
import im.composer.audio.engine.Source;

public class SimpleMixer extends InOut {

	private final Vector<Float> gains = new Vector<Float>();
	private boolean convertMono2Stero = false;

	public SimpleMixer() {
		super(null);
	}

	public SimpleMixer(AudioConfiguration context) {
		super(context);
	}

	@Override
	public synchronized Object addSource(Source s, boolean p) throws SinkIsFullException {
		Object obj = super.addSource(s, p);
		if (gains.size() < getSources().size()) {
			gains.add(1f);
		} else {
			gains.set(getSources().size() - 1, 1f);
		}
		return obj;
	}

	public void setGain(int index, float gain) {
		gains.set(index, gain);
	}

	public float getGain(int index) {
		return gains.get(index);
	}

	public boolean isConvertMono2Stero() {
		return convertMono2Stero;
	}

	public void setConvertMono2Stero(boolean convertMono2Stero) {
		this.convertMono2Stero = convertMono2Stero;
	}

	@Override
	protected void computeBuffer() {
		for (int i = 0; i < getSources().size(); i++) {
			try {
				FloatSampleBuffer fsb = getSources().get(i).getBuffer();
				float gain = gains.get(i);
				int nChannels = Math.min(buf.getChannelCount(), fsb.getChannelCount());
				for (int j = 0; j < nChannels; j++) {
					for (int k = 0; k < bufferSize; k++) {
						buf.getAllChannels()[j][k] += fsb.getAllChannels()[j][k] * gain;
					}
				}
				if (isConvertMono2Stero() && fsb.getChannelCount() == 1 && buf.getChannelCount() > 1) {
					for (int j = 1; j < buf.getChannelCount(); j++) {
						for (int k = 0; k < bufferSize; k++) {
							buf.getAllChannels()[j][k] += fsb.getAllChannels()[0][k] * gain;
						}
					}
				}
			} catch (BufferNotAvailableException e) {
				continue;
			}
		}
	}
}
